Clean up symtab loading in elf loader.
Signed-off-by: Keir Fraser <keir@xensource.com>
unsigned long v_kernend;
unsigned long v_kernentry;
- unsigned int load_bsd_symtab;
-
+ unsigned int load_symtab;
unsigned long symtab_addr;
unsigned long symtab_len;
};
static int
loadelfimage(
char *elfbase, int xch, u32 dom, unsigned long *parray,
- unsigned long vstart);
+ struct domain_setup_info *dsi);
static int
loadelfsymtab(
char *elfbase, int xch, u32 dom, unsigned long *parray,
if ( rc != 0 )
goto error_out;
- if (dsi.load_bsd_symtab)
- loadelfsymtab(image, xc_handle, dom, NULL, &dsi);
-
if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
{
PERROR("Guest OS must load to a page boundary.\n");
goto error_out;
}
- loadelfimage(image, xc_handle, dom, page_array, dsi.v_start);
-
- if (dsi.load_bsd_symtab)
- loadelfsymtab(image, xc_handle, dom, page_array, &dsi);
+ loadelfimage(image, xc_handle, dom, page_array, &dsi);
/* Load the initial ramdisk image. */
if ( initrd_len != 0 )
dsi->v_start = strtoul(p+10, &p, 0);
if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
- dsi->load_bsd_symtab = 1;
+ dsi->load_symtab = 1;
dsi->v_kernstart = kernstart;
dsi->v_kernend = kernend;
dsi->v_kernentry = ehdr->e_entry;
-
dsi->v_end = dsi->v_kernend;
+ loadelfsymtab(elfbase, 0, 0, NULL, dsi);
+
return 0;
}
static int
loadelfimage(
char *elfbase, int xch, u32 dom, unsigned long *parray,
- unsigned long vstart)
+ struct domain_setup_info *dsi)
{
Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
Elf_Phdr *phdr;
for ( done = 0; done < phdr->p_filesz; done += chunksz )
{
- pa = (phdr->p_paddr + done) - vstart;
+ pa = (phdr->p_paddr + done) - dsi->v_start;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_filesz - done;
for ( ; done < phdr->p_memsz; done += chunksz )
{
- pa = (phdr->p_paddr + done) - vstart;
+ pa = (phdr->p_paddr + done) - dsi->v_start;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_memsz - done;
}
}
+ loadelfsymtab(elfbase, xch, dom, parray, dsi);
+
return 0;
}
char *p;
int h, i;
+ if ( !dsi->load_symtab )
+ return 0;
+
p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
ehdr->e_shnum * sizeof(Elf_Shdr));
if (p == NULL)
unsigned long v_kernstart;
unsigned long v_kernend;
unsigned long v_kernentry;
-
- unsigned int load_bsd_symtab;
-
- unsigned long symtab_addr;
- unsigned long symtab_len;
};
static int
loadelfimage(
char *elfbase, int xch, u32 dom, unsigned long *parray,
unsigned long vstart);
-static int
-loadelfsymtab(
- char *elfbase, int xch, u32 dom, unsigned long *parray,
- struct domain_setup_info *dsi);
static void build_e820map(struct mem_map *mem_mapp, unsigned long mem_size)
{
memset(&dsi, 0, sizeof(struct domain_setup_info));
- rc = parseelfimage(image, image_size, &dsi);
- if ( rc != 0 )
+ if ( (rc = parseelfimage(image, image_size, &dsi)) != 0 )
goto error_out;
- if (dsi.load_bsd_symtab)
- loadelfsymtab(image, xc_handle, dom, NULL, &dsi);
-
if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
{
PERROR("Guest OS must load to a page boundary.\n");
loadelfimage(image, xc_handle, dom, page_array, dsi.v_start);
- if (dsi.load_bsd_symtab)
- loadelfsymtab(image, xc_handle, dom, page_array, &dsi);
-
/* Load the initial ramdisk image. */
if ( initrd_len != 0 )
{
}
dsi->v_start = 0x00000000;
- dsi->load_bsd_symtab = 0;
dsi->v_kernstart = kernstart - LINUX_PAGE_OFFSET;
dsi->v_kernend = kernend - LINUX_PAGE_OFFSET;
return 0;
}
-
-
-#define ELFROUND (ELFSIZE / 8)
-
-static int
-loadelfsymtab(
- char *elfbase, int xch, u32 dom, unsigned long *parray,
- struct domain_setup_info *dsi)
-{
- Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
- Elf_Shdr *shdr;
- unsigned long maxva, symva;
- char *p;
- int h, i;
-
- p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
- ehdr->e_shnum * sizeof(Elf_Shdr));
- if (p == NULL)
- return 0;
-
- maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
- symva = maxva;
- maxva += sizeof(int);
- dsi->symtab_addr = maxva;
- dsi->symtab_len = 0;
- maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
- maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-
- shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
- memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
-
- for ( h = 0; h < ehdr->e_shnum; h++ )
- {
- if ( shdr[h].sh_type == SHT_STRTAB )
- {
- /* Look for a strtab @i linked to symtab @h. */
- for ( i = 0; i < ehdr->e_shnum; i++ )
- if ( (shdr[i].sh_type == SHT_SYMTAB) &&
- (shdr[i].sh_link == h) )
- break;
- /* Skip symtab @h if we found no corresponding strtab @i. */
- if ( i == ehdr->e_shnum )
- {
- shdr[h].sh_offset = 0;
- continue;
- }
- }
-
- if ( (shdr[h].sh_type == SHT_STRTAB) ||
- (shdr[h].sh_type == SHT_SYMTAB) )
- {
- if ( parray != NULL )
- xc_map_memcpy(maxva, elfbase + shdr[h].sh_offset, shdr[h].sh_size,
- xch, dom, parray, dsi->v_start);
-
- /* Mangled to be based on ELF header location. */
- shdr[h].sh_offset = maxva - dsi->symtab_addr;
-
- dsi->symtab_len += shdr[h].sh_size;
- maxva += shdr[h].sh_size;
- maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
- }
-
- shdr[h].sh_name = 0; /* Name is NULL. */
- }
-
- if ( dsi->symtab_len == 0 )
- {
- dsi->symtab_addr = 0;
- goto out;
- }
-
- if ( parray != NULL )
- {
- *(int *)p = maxva - dsi->symtab_addr;
- sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
- memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
- sym_ehdr->e_phoff = 0;
- sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
- sym_ehdr->e_phentsize = 0;
- sym_ehdr->e_phnum = 0;
- sym_ehdr->e_shstrndx = SHN_UNDEF;
-
- /* Copy total length, crafted ELF header and section header table */
- xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
- ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
- dsi->v_start);
- }
-
- dsi->symtab_len = maxva - dsi->symtab_addr;
- dsi->v_end = round_pgup(maxva);
-
- out:
- if ( p != NULL )
- free(p);
-
- return 0;
-}
BUG();
memset(&dsi, 0, sizeof(struct domain_setup_info));
+ dsi.image_addr = (unsigned long)image_start;
+ dsi.image_len = image_len;
printk("*** LOADING DOMAIN 0 ***\n");
alloc_start = page_to_phys(page);
alloc_end = alloc_start + (d->tot_pages << PAGE_SHIFT);
- rc = parseelfimage(image_start, image_len, &dsi);
- if ( rc != 0 )
+ if ( (rc = parseelfimage(&dsi)) != 0 )
return rc;
- if (dsi.load_bsd_symtab)
- loadelfsymtab(image_start, 0, &dsi);
-
/* Align load address to 4MB boundary. */
dsi.v_start &= ~((1UL<<22)-1);
write_ptbase(ed);
/* Copy the OS image and free temporary buffer. */
- (void)loadelfimage(image_start);
-
- if (dsi.load_bsd_symtab)
- loadelfsymtab(image_start, 1, &dsi);
+ (void)loadelfimage(&dsi);
init_domheap_pages(
_image_start, (_image_start+image_len+PAGE_SIZE-1) & PAGE_MASK);
#define FORCE_XENELF_IMAGE 0
#endif
+static void loadelfsymtab(struct domain_setup_info *dsi, int doload);
static inline int is_loadable_phdr(Elf_Phdr *phdr)
{
return ((phdr->p_type == PT_LOAD) &&
((phdr->p_flags & (PF_W|PF_X)) != 0));
}
-int parseelfimage(char *elfbase,
- unsigned long elfsize,
- struct domain_setup_info *dsi)
+int parseelfimage(struct domain_setup_info *dsi)
{
- Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
+ Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
unsigned long kernstart = ~0UL, kernend=0UL;
char *shstrtab, *guestinfo=NULL, *p;
+ char *elfbase = (char *)dsi->image_addr;
int h;
if ( !elf_sanity_check(ehdr) )
return -EINVAL;
- if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
+ if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > dsi->image_len )
{
printk("ELF program headers extend beyond end of image.\n");
return -EINVAL;
}
- if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
+ if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > dsi->image_len )
{
printk("ELF section headers extend beyond end of image.\n");
return -EINVAL;
dsi->v_start = simple_strtoul(p+10, &p, 0);
if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
- dsi->load_bsd_symtab = 1;
-
+ dsi->load_symtab = 1;
}
dsi->v_kernstart = kernstart;
dsi->v_kernend = kernend;
dsi->v_kernentry = ehdr->e_entry;
-
dsi->v_end = dsi->v_kernend;
+ loadelfsymtab(dsi, 0);
+
return 0;
}
-int loadelfimage(char *elfbase)
+int loadelfimage(struct domain_setup_info *dsi)
{
- Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
+ char *elfbase = (char *)dsi->image_addr;
+ Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
Elf_Phdr *phdr;
int h;
phdr->p_memsz - phdr->p_filesz);
}
+ loadelfsymtab(dsi, 1);
+
return 0;
}
#define ELFROUND (ELFSIZE / 8)
-int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi)
+static void loadelfsymtab(struct domain_setup_info *dsi, int doload)
{
- Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
+ Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr;
Elf_Shdr *shdr;
unsigned long maxva, symva;
- char *p;
+ char *p, *elfbase = (char *)dsi->image_addr;
int h, i;
+ if ( !dsi->load_symtab )
+ return;
+
maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
symva = maxva;
maxva += sizeof(int);
dsi->symtab_len = 0;
maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
- if (doload) {
- p = (void *)symva;
-
- shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
- memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
- } else {
- shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff);
- p = NULL; /* XXX: gcc */
+ if ( doload )
+ {
+ p = (void *)symva;
+ shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
+ memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr));
+ }
+ else
+ {
+ p = NULL;
+ shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff);
}
for ( h = 0; h < ehdr->e_shnum; h++ )
/* Skip symtab @h if we found no corresponding strtab @i. */
if ( i == ehdr->e_shnum )
{
- if (doload) {
- shdr[h].sh_offset = 0;
- }
+ if (doload) {
+ shdr[h].sh_offset = 0;
+ }
continue;
}
}
if ( (shdr[h].sh_type == SHT_STRTAB) ||
(shdr[h].sh_type == SHT_SYMTAB) )
{
- if (doload) {
- memcpy((void *)maxva, elfbase + shdr[h].sh_offset,
- shdr[h].sh_size);
+ if (doload) {
+ memcpy((void *)maxva, elfbase + shdr[h].sh_offset,
+ shdr[h].sh_size);
- /* Mangled to be based on ELF header location. */
- shdr[h].sh_offset = maxva - dsi->symtab_addr;
+ /* Mangled to be based on ELF header location. */
+ shdr[h].sh_offset = maxva - dsi->symtab_addr;
- }
- dsi->symtab_len += shdr[h].sh_size;
- maxva += shdr[h].sh_size;
- maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+ }
+ dsi->symtab_len += shdr[h].sh_size;
+ maxva += shdr[h].sh_size;
+ maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
}
- if (doload) {
- shdr[h].sh_name = 0; /* Name is NULL. */
- }
+ if ( doload )
+ shdr[h].sh_name = 0; /* Name is NULL. */
}
if ( dsi->symtab_len == 0 )
{
dsi->symtab_addr = 0;
- goto out;
+ return;
}
- if (doload) {
- *(int *)p = maxva - dsi->symtab_addr;
- sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
- memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
- sym_ehdr->e_phoff = 0;
- sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
- sym_ehdr->e_phentsize = 0;
- sym_ehdr->e_phnum = 0;
- sym_ehdr->e_shstrndx = SHN_UNDEF;
+ if ( doload )
+ {
+ *(int *)p = maxva - dsi->symtab_addr;
+ sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
+ memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
+ sym_ehdr->e_phoff = 0;
+ sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
+ sym_ehdr->e_phentsize = 0;
+ sym_ehdr->e_phnum = 0;
+ sym_ehdr->e_shstrndx = SHN_UNDEF;
}
-#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) /* XXX */
-
dsi->symtab_len = maxva - dsi->symtab_addr;
- dsi->v_end = round_pgup(maxva);
-
- out:
-
- return 0;
+ dsi->v_end = maxva;
}
/*
#endif
struct domain_setup_info;
-extern int loadelfimage(char *);
-extern int loadelfsymtab(char *, int, struct domain_setup_info *);
-extern int parseelfimage(char *, unsigned long, struct domain_setup_info *);
+extern int loadelfimage(struct domain_setup_info *);
+extern int parseelfimage(struct domain_setup_info *);
#ifdef Elf_Ehdr
extern int elf_sanity_check(Elf_Ehdr *ehdr);
struct domain_setup_info
{
+ /* Initialised by caller. */
+ unsigned long image_addr;
+ unsigned long image_len;
+ /* Initialised by loader: Public. */
unsigned long v_start;
unsigned long v_end;
unsigned long v_kernstart;
unsigned long v_kernend;
unsigned long v_kernentry;
-
- unsigned int load_bsd_symtab;
-
+ /* Initialised by loader: Private. */
+ unsigned int load_symtab;
unsigned long symtab_addr;
unsigned long symtab_len;
};